Serverless Framework + StepFunctionsの構成でStateMachineを60個以上作ろうとしたらエラーになったので、暫定対応しました。
はじめに
好物はインフラとフロントエンドのかじわらゆたかです。
件名の通りなのですが、Serverless Framework とそのプラグインであるserverless-step-functionsを用いた環境でStatemachineを60個以上つくろうとするとエラーとなります。 プラグインにプルリクエストを出すことも考えたのですが、実際に開発中の案件で使っているのもあったのでPatchファイルで暫定対応をしたので、その内容を記載したいと思います。
再現と原因
今回の検証は以下の環境で行いました。
$ node --version v13.12.0 $ sls --version Framework Core: 1.67.0 Plugin: 3.6.4 SDK: 2.3.0 Components: 2.28.0 serverless-step-functions : 2.17.4
以下のようなServerless Frameworkのyamlファイルを用意しデプロイすると再現ができます。
service: serverless-many-statemachine provider: name: aws runtime: nodejs12.x region: ap-northeast-1 plugins: - serverless-step-functions stepFunctions: stateMachines: StateMachine1: name: TestStateMachine1 definition: StartAt: HelloWorld States: HelloWorld: Type: Succeed StateMachine2: name: TestStateMachine2 definition: StartAt: HelloWorld States: HelloWorld: Type: Succeed 中略 StateMachine59: name: TestStateMachine59 definition: StartAt: HelloWorld States: HelloWorld: Type: Succeed StateMachine60: name: TestStateMachine60 definition: StartAt: HelloWorld States: HelloWorld: Type: Succeed
上記をデプロイしようとすると以下ようなエラーが発生します。
$ sls deploy --aws-profile cm-di-div Serverless: Packaging service... Serverless: Uploading CloudFormation file to S3... Serverless: Uploading artifacts... Serverless: Validating template... Error -------------------------------------------------- Error: The CloudFormation template is invalid: Template format error: Outputs count 61 is greater than max allowed 60 以下省略
書いてあるエラーメッセージのとおりなのですが、Serverless Frameworkが作ったCloudFormationのテンプレートがCloudFormationのOutputs の上限に達してしまったため発生したエラーのようです。
こちらはドキュメントにも以下のように記載がされています。
制限 | 説明 | 値 |
---|---|---|
出力 | AWS CloudFormation テンプレートで宣言できる出力の最大数。 | 60 個の出力 |
AWS CloudFormation の制限 - AWS CloudFormation
ワークアラウンドとしての対応
Serverless Step Functions プラグインでStateMachineの情報をCloudformationのOutputに記載している箇所は以下になります。
_.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs, newStateMachineOutPutObject);
Deployすることを目的とするならばハイライトされている行を削除することでデプロイは行えるようになります。 ですが、そのような対応ですと削除した箇所を忘れたり、別の人がデプロイするといった際にその対応を忘れてデプロイが失敗してしまうと言った事になってしまうかもしれません。 そのためこのOutputの抑制を行うPatchを書いて暫定措置とします。
NoOutputStatemachineARN.patch
--- ./compileStateMachines.js 2020-04-04 15:44:30.000000000 +0900 +++ ./compileStateMachines_noOutputs.js 2020-04-04 15:44:22.000000000 +0900 @@ -243,9 +243,6 @@ module.exports = { [stateMachineOutputLogicalId]: stateMachineOutPutObject, }; - _.merge(this.serverless.service.provider.compiledCloudFormationTemplate.Outputs, - newStateMachineOutPutObject); - return BbPromise.resolve(); }); }
あとは上記のパッチを以下な感じで適用することで、デプロイが行えるようになります。
patch -u node_modules/serverless-step-functions/lib/deploy/stepFunctions/compileStateMachines.js < NoOutputStatemachineARN.patch
またPatchを戻す場合は以下のような形になります。
patch -R node_modules/serverless-step-functions/lib/deploy/stepFunctions/compileStateMachines.js < NoOutputStatemachineARN.patch
結論
serverless-step-functions を使って大量のステートマシンを書いている際にデプロイできないってケースに遭遇した際に、 ワークアラウンドではありますがこの方法をとることでデプロイが行えるようになります。